#ifndef __IO_H
#define __IO_H

#include <iostream>
#include <fstream>
#include <sstream>


struct Sink {
    std::ofstream out;

    Sink(const std::string& name, bool append = false) {

        out.exceptions(std::ofstream::failbit|std::ofstream::badbit);
        out.open(name, (append ?
                        std::ios::out|std::ios::app|std::ios::binary :
                        std::ios::out|std::ios::trunc|std::ios::binary));
    }

    ~Sink() { out.close(); }

    template <typename T>
    void operator<<(const T& t) {
        out << t << "\n";
    }

    void flush() {
        out.flush();
    }
};

struct Source {
    std::ifstream inp;
    
    Source(const std::string& name) {
        inp.exceptions(std::ifstream::failbit|std::ifstream::badbit);
        inp.open(name, std::ios::in|std::ios::binary);
    }

    ~Source() { inp.close(); }

    template <typename T>
    void operator>>(T& t) {
        inp >> t;
    }
};


void read_string(Source& fin, std::string& out, size_t n) {

    fin.inp >> std::noskipws;
    
    unsigned char c;
    fin >> c;
    for (size_t i = 0; i < n; ++i) {
        fin >> c;
        out += c;
    }

    fin.inp >> std::skipws;
}


#endif
